package cn.smile.business.basic.impl;

import cn.smile.bean.dto.basic.ExpenseItemDTO;
import cn.smile.bean.dto.basic.MyShopDTO;
import cn.smile.bean.dto.basic.VoucherDTO;
import cn.smile.bean.entity.basic.Voucher;
import cn.smile.bean.form.basic.item.QueryItemForm;
import cn.smile.bean.form.basic.voucher.AddVoucherForm;
import cn.smile.bean.form.basic.voucher.QueryVoucherForm;
import cn.smile.bean.form.basic.voucher.UpdateVoucherForm;
import cn.smile.business.basic.*;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.commons.enums.basic.VoucherStatusEnum;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import cn.smile.repository.basic.VoucherMapper;
import cn.smile.utils.BeanCopy;
import cn.smile.utils.DateFormatUtil;
import cn.smile.utils.VoucherUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class VoucherServiceImpl extends BaseServiceImpl<VoucherMapper, Voucher> implements IVoucherService {
    @Resource
    private IMyShopService shopService;
    @Resource
    private IVoucherItemService voucherItemService;
    @Resource
    private IExpenseItemService itemService;
    @Resource
    private IVoucherMemberService vouMemService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addEntity(AddVoucherForm form) {
        log.info("[VoucherServiceImpl].[addEntity] ------> 新增代金券模板 Start");
        this.checkParams(form);
        Voucher entity = BeanCopy.copyBean(form, Voucher.class);
        MyShopDTO shop = shopService.getMyShop();
        entity.setShopId(shop.getId());
        entity.setVoucherStatus(VoucherUtil.getStatus(form.getValidityStart(), form.getValidityEnd()).getSn());
        boolean flag = super.create(entity);
        if (flag) {
            voucherItemService.saveEntity(entity.getId(), form.getItemList());
        }
        log.info("[VoucherServiceImpl].[addEntity] ------> 新增代金券模板 End, flag = {}", flag);
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateEntity(UpdateVoucherForm form) {
        log.info("[VoucherServiceImpl].[updateEntity] ------> 更新代金券模板 Start");
        this.checkParams(form);
        Voucher entity = BeanCopy.copyBean(form, Voucher.class);
        MyShopDTO shop = shopService.getMyShop();
        entity.setShopId(shop.getId());
        entity.setVoucherStatus(VoucherUtil.getStatus(form.getValidityStart(), form.getValidityEnd()).getSn());
        boolean flag = super.update(entity);
        if (flag) {
            voucherItemService.saveEntity(entity.getId(), form.getItemList());
        }
        log.info("[VoucherServiceImpl].[updateEntity] ------> 更新代金券模板 End, flag = {}", flag);
        return flag;
    }

    @Override
    public IPage<VoucherDTO> getPage(QueryVoucherForm form) {
        log.info("[VoucherServiceImpl].[getPage] ------> 分页查询代金券信息 Start, form = {}", JSON.toJSONString(form));
        Page<Voucher> basePage = baseMapper.selectPage(form.queryPage(), this.getQueryParams(form));
        IPage<VoucherDTO> dataPage = BeanCopy.copyPage(basePage, VoucherDTO.class);
        this.setDetail(dataPage.getRecords());
        log.info("[VoucherServiceImpl].[getPage] ------> 分页查询代金券信息 End");
        return dataPage;
    }

    @Override
    public List<VoucherDTO> getList(QueryVoucherForm form) {
        log.info("[VoucherServiceImpl].[getList] ------> 列表查询代金券信息 Start, form = {}", JSON.toJSONString(form));
        List<Voucher> baseList = baseMapper.selectList(this.getQueryParams(form));
        List<VoucherDTO> dataList = BeanCopy.copyList(baseList, VoucherDTO.class);
        this.setDetail(dataList);
        log.info("[VoucherServiceImpl].[getList] ------> 列表查询代金券信息 End");
        return dataList;
    }

    @Override
    public VoucherDTO getVoucherById(String id) {
        log.info("[VoucherServiceImpl].[getVoucherById] ------> 根据代金券ID查询代金券 Start, id = {}", id);
        Voucher base = super.get(id);
        VoucherDTO entity = BeanCopy.copyBean(base, VoucherDTO.class);
        this.setDetail(Lists.newArrayList(entity));
        log.info("[VoucherServiceImpl].[getVoucherById] ------> 根据代金券ID查询代金券 End");
        return entity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delVoucher(String id) {
        log.info("[VoucherServiceImpl].[delVoucher] ------> 根据代金券ID删除代金券 Start, id = {}", id);
        boolean flag = super.delById(id);
        if (flag) {
            voucherItemService.delByVoucherId(id);
        }
        log.info("[VoucherServiceImpl].[delVoucher] ------> 根据代金券ID删除代金券 End, flag = {}", flag);
        return flag;
    }

    @Override
    public void updateStatus() {
        log.info("[VoucherServiceImpl].[updateStatus] ------> 更新全部代金券状态 Start");
        QueryVoucherForm form = new QueryVoucherForm();
        form.setUseShopFlag(Boolean.FALSE);
        List<VoucherDTO> dataList = this.getList(form);
        if (!CollectionUtils.isEmpty(dataList)) {
            for (VoucherDTO dto : dataList) {
                dto.setVoucherStatus(VoucherUtil.getStatus(dto.getValidityStart(), dto.getValidityEnd()).getSn());
                super.update(dto);
            }
        }
        log.info("[VoucherServiceImpl].[updateStatus] ------> 更新全部代金券状态 End");
    }

    /**
     * 写入代金券详细信息
     *
     * @param dataList 数据集合
     */
    private void setDetail(List<VoucherDTO> dataList) {
        if (!CollectionUtils.isEmpty(dataList)) {
            List<String> ids = Lists.newArrayList();
            dataList.forEach(data -> ids.add(data.getId()));
            Map<String, List<String>> itemIdsMap = voucherItemService.getItemIdsMap(ids);
            Map<String, ExpenseItemDTO> itemMap = itemService.getItemMap(new QueryItemForm());
            Map<String, Integer> issueNumMap = vouMemService.countIssueNum(ids);
            for (VoucherDTO entity : dataList) {
                entity.setVoucherStatusName(VoucherStatusEnum.get(entity.getVoucherStatus()).getMsg());
                entity.setValidityDate(String.format("%s - %s", DateFormatUtil.parseDateToStr(DateFormatUtil.localDateToDate(entity.getValidityStart()), DateFormatUtil.DATE_TIME_FORMAT_7), DateFormatUtil.parseDateToStr(DateFormatUtil.localDateToDate(entity.getValidityEnd()), DateFormatUtil.DATE_TIME_FORMAT_7)));
                if (itemIdsMap.containsKey(entity.getId())) {
                    List<String> itemList = itemIdsMap.get(entity.getId());
                    entity.setItemList(itemList);
                    entity.setItemNames(VoucherUtil.getItemNames(itemList, itemMap));
                }
                entity.setIssueNum(issueNumMap.getOrDefault(entity.getId(), NumberConstant.ZERO));
            }
        }
    }

    /**
     * 组装查询参数
     *
     * @param form 查询参数对象
     * @return 数据库查询对象
     */
    private LambdaQueryWrapper<Voucher> getQueryParams(QueryVoucherForm form) {
        LambdaQueryWrapper<Voucher> qw = new QueryWrapper<Voucher>().lambda().eq(Voucher::getDeleted, Boolean.FALSE);
        if (form.getUseShopFlag()) {
            MyShopDTO shop = shopService.getMyShop();
            qw.eq(Voucher::getShopId, shop.getId());
        }
        if (!ObjectUtils.isEmpty(form.getVoucherName())) {
            qw.like(Voucher::getVoucherName, form.getVoucherName());
        }
        if (!CollectionUtils.isEmpty(form.getVoucherStatusList())) {
            qw.in(Voucher::getVoucherStatus, form.getVoucherStatusList());
        }
        return qw;
    }

    /**
     * 检查参数
     *
     * @param form 请求参数
     */
    private void checkParams(AddVoucherForm form) {
        if (form.getValidityEnd().isBefore(form.getValidityStart())) {
            throw new BusinessException(MyResponseCode.VOUCHER_DATE_ERROR);
        }
    }
}
